home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / tex / src / specialhost / tpic.c < prev    next >
C/C++ Source or Header  |  1991-07-11  |  8KB  |  376 lines

  1. /** tpic.c **/
  2.  
  3.  
  4. static void flushPath    (int invis);
  5. static void flushDashed     (int dotted);
  6. static void flushSpline     (void);
  7. static void arc         (int invis);
  8.  
  9. static void dot_at       (int x, int y);
  10. static void line_btw     (int x0, int y0, int x1, int y1);
  11. static void draw_ellipse (int xc, int yc, int xr, int yr);
  12.  
  13.  
  14. struct tpic_msg   *tp;
  15. struct driver_map *dm;
  16.  
  17. long hres, vres;
  18. long path_len;
  19.  
  20. #define xRESOLUTION    hres
  21. #define yRESOLUTION    vres
  22.  
  23. struct bitmap     map;
  24. long          upper_limit;
  25. long          lower_limit;
  26.  
  27.  
  28.  
  29.  
  30. /*
  31.  * APPROXIMATE integer distance between two points
  32.  */
  33. #define    dist(x0, y0, x1, y1)    (abs(x0-x1)+abs(y0-y1))
  34.  
  35. #define    TWOPI        (3.14159265359*2.0)
  36.  
  37. #define xCONV_PT(x) \
  38.   ((x) < 0 ? -((-(x) * hres + 500) / 1000) \
  39.        : (((x) * hres + 500) / 1000) )
  40. #define yCONV_PT(y) \
  41.   ((y) < 0 ? -((-(y) * vres + 500) / 1000) \
  42.        : (((y) * vres + 500) / 1000) )
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49. void work_with_tpic(struct tpic_msg *tpic, struct driver_map *dmap,
  50.             long hresolution, long vresolution)
  51. {
  52.   tp = tpic;
  53.   dm = dmap;
  54.  
  55.   hres = hresolution;
  56.   vres = vresolution;
  57.   path_len = tp->path_len;
  58.   
  59.   /* Initialisierung fuer 'graphics.c' */
  60.   map.width  = dm->width;
  61.   map.height = dm->height;
  62.   map.pixptr = dm->pixptr;
  63.   upper_limit = dm->upper_limit;
  64.   lower_limit = dm->lower_limit;
  65.  
  66.   device_SetPenSize(xCONV_PT(tpic->pen_size), yCONV_PT(tpic->pen_size));
  67.  
  68.   switch (tpic->tpic_com) {
  69.     case TPIC_FP:
  70.     flushPath(FALSE);
  71.     case TPIC_IP:
  72.     flushPath(TRUE);
  73.     break;
  74.     case TPIC_DA:
  75.     flushDashed(FALSE);
  76.     break;
  77.     case TPIC_DT:
  78.     flushDashed(TRUE);
  79.     break;
  80.     case TPIC_SP:
  81.     case TPIC_SPB:
  82.     flushSpline();
  83.     break;
  84.     case TPIC_AR:
  85.     arc(FALSE);
  86.     break;
  87.     case TPIC_IA:
  88.     arc(TRUE);
  89.     break;
  90.     default:
  91.     break;
  92.   }
  93. }
  94.  
  95.  
  96.  
  97. /*----------------------------------------------------------------*/
  98.  
  99.  
  100. static void flushPath(int invis)
  101. {
  102.   int i, x, y;
  103.  
  104.   if (tp->path_len == 1) {
  105.     pline("FP/IP path less than 2 points - ignored");
  106.   }
  107.   else {
  108.     if (invis) {
  109.       /* not jet implemented */
  110.       ;
  111.     }
  112.     else {
  113.       x = dm->x;
  114.       y = dm->y;
  115.       for (i=1; i<tp->path_len; i++) {
  116.         device_DrawLine(
  117.           x + xCONV_PT(tp->xx[i]), y + yCONV_PT(tp->yy[i]),
  118.           x + xCONV_PT(tp->xx[i+1]), y + yCONV_PT(tp->yy[i+1]));
  119.       }
  120.     }
  121.   }
  122. }
  123.  
  124.  
  125. static void flushDashed(int dotted)
  126. {
  127.   long *xx = &(tp->xx[0]);
  128.   long *yy = &(tp->yy[0]);
  129.   int i, numdots, x0, y0, x1, y1;
  130.   int cx0, cy0, cx1, cy1;
  131.   double d, spacesize, a, b, dx, dy, milliperdash;
  132.   float inchesperdash;
  133.  
  134.   sscanf(tp->opt_float[0], "%g", &inchesperdash);
  135.   if (tp->path_len <= 1 || inchesperdash <= 0.0) {
  136.     pline("*** illegal conditions for dotted/dashed line (%d, %d)", tp->path_len, inchesperdash);
  137.     return;
  138.   }
  139.  
  140.     milliperdash = inchesperdash * 1000.0;
  141.     x0 = xx[1];    y0 = yy[1];
  142.     x1 = xx[2];    y1 = yy[2];
  143.     dx = x1 - x0;
  144.     dy = y1 - y0;
  145.     if (dotted) {
  146.     numdots = sqrt(dx*dx + dy*dy) / milliperdash + 0.5;
  147.     if (numdots == 0) numdots = 1;
  148.     for (i=0; i <= numdots; i++) {
  149.         a = (float) i / (float) numdots;
  150.         cx0 = x0 + a*dx + 0.5;
  151.         cy0 = y0 + a*dy + 0.5;
  152.         dot_at(cx0, cy0);
  153.     }
  154.     } else {
  155.     d = sqrt(dx*dx + dy*dy);
  156.     if (d <= 2.0*milliperdash)
  157.         line_btw(x0, y0, x1, y1);
  158.     else {
  159.         numdots = d / (2.0*milliperdash) + 1.0;
  160.         spacesize = (d - numdots * milliperdash) / (numdots - 1);
  161.         for (i=0; i<numdots-1; i++) {
  162.         a = i * (milliperdash + spacesize) / d;
  163.         b = a + milliperdash / d;
  164.         cx0 = x0 + a*dx + 0.5;
  165.         cy0 = y0 + a*dy + 0.5;
  166.         cx1 = x0 + b*dx + 0.5;
  167.         cy1 = y0 + b*dy + 0.5;
  168.         line_btw(cx0, cy0, cx1, cy1);
  169.         b += spacesize / d;
  170.         }
  171.         cx0 = x0 + b*dx + 0.5;
  172.         cy0 = y0 + b*dy + 0.5;
  173.         line_btw(cx0, cy0, x1, y1);
  174.     }
  175.     }
  176. }
  177.  
  178. static void flushSpline(void)
  179. {
  180.   long *xx = &(tp->xx[0]);
  181.   long *yy = &(tp->yy[0]);
  182.   int xp, yp, N, lastx, lasty;
  183.   int t1, t2, t3, steps, j;
  184.   int i, w;
  185.   int ipd;
  186.  
  187. #if 0
  188.   if( *cp ) {
  189.     float inchesPerDash;
  190.  
  191.     if( sscanf(cp, "%f", &inchesPerDash) != 1 ) {
  192.     Warning("Illegal format for dotted/dashed spline", "");
  193.     return;
  194.     }
  195.  
  196.     ipd = (int)(1000.0 * inchesPerDash);    /* to get milli-inches */
  197.   }
  198.  
  199.   if( ipd < 0 )    {    /* dotted */
  200.   } else {        /* dashed */
  201.   }
  202. #endif
  203.  
  204.   N = path_len + 1;
  205.   xx[0] = xx[1];    yy[0] = yy[1];
  206.   xx[N] = xx[N-1];    yy[N] = yy[N-1];
  207.   for (i=0; i<N-1; i++) {    /* interval */
  208.     /* original was:
  209.      * steps = (dist(xx[i], yy[i], xx[i+1], yy[i+1]) +
  210.      *     dist(xx[i+1], yy[i+1], xx[i+2], yy[i+2])) / 80;
  211.      */
  212.     steps = (dist(xx[i], yy[i], xx[i+1], yy[i+1]) +
  213.          dist(xx[i+1], yy[i+1], xx[i+2], yy[i+2])) * xRESOLUTION / 4000;
  214.  
  215.      w  = 500 / steps;
  216.     t1 = w * w / 20;
  217.     w -= 500;
  218.     t2 = (750000 - w * w) / 10;
  219.     w -= 500;
  220.     t3 = w * w / 20;
  221.     lastx = (t1*xx[i+2] + t2*xx[i+1] + t3*xx[i] + 50000) / 100000;
  222.     lasty = (t1*yy[i+2] + t2*yy[i+1] + t3*yy[i] + 50000) / 100000;
  223.  
  224.     for (j=1; j<steps; j++) {    /* points within */
  225.         w  = (j*1000 + 500) / steps;
  226.         t1 = w * w / 20;
  227.         w -= 500;
  228.         t2 = (750000 - w * w) / 10;
  229.         w -= 500;
  230.         t3 = w * w / 20;
  231.         xp = (t1*xx[i+2] + t2*xx[i+1] + t3*xx[i] + 50000) / 100000;
  232.         yp = (t1*yy[i+2] + t2*yy[i+1] + t3*yy[i] + 50000) / 100000;
  233.         line_btw(lastx, lasty, xp, yp);
  234.         lastx = xp;
  235.         lasty = yp;
  236.     }
  237.   }
  238. }
  239.  
  240. static void arc(int invis)
  241. {
  242.   int xc, yc, xrad, yrad, n;
  243.   int lastx, lasty;
  244.   float start_angle, end_angle, angle, theta, r;
  245.   double xradius, yradius;
  246.  
  247.   xc   = tp->opt_long[0];
  248.   yc   = tp->opt_long[1];
  249.   xrad = tp->opt_long[2];
  250.   yrad = tp->opt_long[3];
  251.   sscanf(tp->opt_float[0], "%g", &start_angle);
  252.   sscanf(tp->opt_float[1], "%g", &end_angle);
  253.  
  254.   /* fuer `invis' == true sollte die Ellipse nicht gezeichnet, sondern
  255.    * nur ausgefuellt werden.... wir machen nichts...
  256.    */
  257.   if( invis )
  258.     return;
  259.  
  260.   /* ... und Warnung fuer folgende Faelle ?? */
  261.   if( start_angle > end_angle ) {
  262.     angle = start_angle;  start_angle = end_angle;  end_angle = angle;
  263.   }
  264.   if( xrad < 0 ) xrad = -xrad;
  265.   if( yrad < 0 ) yrad = -yrad;
  266.  
  267.   /* We have a specialized fast way to draw closed circles/ellipses */
  268.   if (start_angle <= 0.0 && end_angle >= 6.283) {
  269.     draw_ellipse(xc, yc, xrad, yrad);
  270.     return;
  271.   }
  272.  
  273.   r = ((float) (xrad + yrad)) / 2.0;
  274.   theta = sqrt(1.0 / r);
  275.   n = 0.3 * TWOPI / theta + 0.5;
  276.   if (n < 12)
  277.     n = 12;
  278.   else if (n > 80)
  279.     n = 80;
  280.   /* n /= 2; */
  281.   theta = TWOPI / n;
  282.  
  283.   xradius = xrad;
  284.   yradius = yrad;
  285.   lastx = xc + (int)(xradius * cos(start_angle) + 0.5);
  286.   lasty = yc + (int)(yradius * sin(start_angle) + 0.5);
  287.  
  288. #ifdef __GNUC__
  289.   /* GCC lib fuer den ST hat in _addsf3() anscheinend einen Fehler :-( */
  290.   angle = (double)start_angle + theta;
  291. #else
  292.   angle = start_angle + theta;
  293. #endif
  294.  
  295.   n += 10;
  296.   while (--n > 0 && angle < end_angle) {
  297.     xrad = xc + (int) (xradius*cos(angle) + 0.5);
  298.     yrad = yc + (int) (yradius*sin(angle) + 0.5);
  299.     line_btw(lastx, lasty, xrad, yrad);
  300.     lastx = xrad;
  301.     lasty = yrad;
  302.     angle += theta;
  303.   }
  304.  
  305.   if( n <= 0 ) {
  306.     pline("Error: in ellipse startangle %f endangle %f (theta %f)",
  307.     start_angle, end_angle, theta);
  308.   }
  309.  
  310.   xrad = xc + (int)(xradius*cos(end_angle) + 0.5);
  311.   yrad = yc + (int)(yradius*sin(end_angle) + 0.5);
  312.   line_btw(lastx, lasty, xrad, yrad);
  313. }
  314.  
  315.  
  316.  
  317. /*-------------------------------------------------------------------*/
  318.  
  319.   static void
  320. dot_at(int x, int y)
  321. {
  322.   x = dm->x + xCONV_PT(x);
  323.   y = dm->y + yCONV_PT(y);
  324.  
  325.   device_DrawPoint(x, y);
  326. }
  327.  
  328.  
  329.   static void
  330. line_btw(int x0, int y0, int x1, int y1)
  331. {
  332.   x0 = dm->x + xCONV_PT(x0);
  333.   y0 = dm->y + yCONV_PT(y0);
  334.   x1 = dm->x + xCONV_PT(x1);
  335.   y1 = dm->y + yCONV_PT(y1);
  336.  
  337.   device_DrawLine(x0, y0, x1, y1);
  338. }
  339.  
  340.  
  341.  
  342.  
  343. /*
  344.  * Draw an ellipse with the indicated center and radices.
  345.  */
  346.   static void
  347. draw_ellipse(int xc, int yc, int xr, int yr)
  348. { double angle, theta;
  349.   int n, px0, py0, px1, py1;
  350.  
  351.   angle = (xr + yr) / 2.0;
  352.   theta = sqrt(1.0 / angle);
  353.   n = TWOPI / theta + 0.5;
  354.   if (n < 12)
  355.     n = 12;
  356.   else if (n > 80)
  357.     n = 80;
  358.   n /= 2;
  359.   theta = TWOPI / n;
  360.  
  361.   px0 = xc + xr;    /* cos(0) = 1 */
  362.   py0 = yc;        /* Sin(0) = 0 */
  363.   angle = theta;
  364.  
  365.   while (angle <= TWOPI) {
  366.     px1 = xc + xr*cos(angle) + 0.5;
  367.     py1 = yc + yr*sin(angle) + 0.5;
  368.     line_btw(px0, py0, px1, py1);
  369.     px0 = px1;
  370.     py0 = py1;
  371.     angle += theta;
  372.   }
  373.   line_btw(px0, py0, xc + xr, yc);
  374. }
  375.  
  376.